#include "utility.h"
ssize_t __write_all(int fd, const void *buf, size_t count) {
    size_t total_written = 0;
    const char *ptr = buf;

    while (total_written < count) {
        ssize_t written = write(fd, ptr + total_written, count - total_written);
        if (written == -1) {
            // 处理错误（如信号中断 EINTR）
            if (errno == EINTR) continue; // 可重试的错误
            else return -1; // 其他错误直接返回
        }
        if (written == 0) break; // 某些情况下可能返回 0（如非阻塞模式）
        total_written += written;
    }
    return total_written;
}

/**
 * 从文件描述符中读取全部指定字节（或直到错误/EOF）
 * @param fd    文件描述符（如套接字、普通文件）
 * @param buf   目标缓冲区
 * @param nbytes 要求读取的字节数
 * @return      成功读取的总字节数（可能小于nbytes，若遇到EOF），出错返回-1
 */
ssize_t __read_all(int fd, void *buf, size_t nbytes) {
    size_t total_read = 0;     // 累计已读取字节
    char *ptr = buf;           // 当前缓冲区指针
    ssize_t n;                 // 单次read的返回值

    while (total_read < nbytes) {
        n = read(fd, ptr + total_read, nbytes - total_read);
        if (n == -1) {
            // 处理可恢复错误（如信号中断）
            if (errno == EINTR) continue;
            else return -1;
        } else if (n == 0) {
            // EOF（已无数据可读）
            break;
        }
        total_read += n;
    }
    return total_read;  // 可能等于nbytes（成功）或小于nbytes（遇到EOF）
}
/**
 * 打开指定的tap网卡
 * @param tap_name  tap网卡名
 * @return          成功的fd文件描述符号码 出错-1
 */
int open_tap(char * tap_name){
    int fd = open("/dev/net/tun", O_RDWR);
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(struct ifreq));
    strncpy(ifr.ifr_ifrn.ifrn_name, tap_name, sizeof(tap_name));
    ifr.ifr_ifru.ifru_flags = IFF_TAP | IFF_NO_PI;
    if (ioctl(fd, TUNSETIFF, &ifr) != 0)
    {
        return -1;
    };
    return fd;
}

uint16_t pck_checksum(const void *buf, const int buf_len)
{
    uint16_t *ptr = (uint16_t *)buf;
    uint32_t sum = 0;
    int index = 0;
    for (size_t i = 0; i < buf_len; i += 2)
    {
        index = i / 2;
        sum += ptr[index];
        uint32_t temph = sum >> 16;
        uint32_t templ = sum & 0xffff;
        sum = temph + templ;
    }
    return ~((uint16_t)sum);
}